package database

import (
	"common/config"
	"common/logs"
	"context"
	"database/sql"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"gorm.io/gorm/schema"
	"log"
	"time"
)

type MysqlManager struct {
	Client *gorm.DB // 单机
	DB     *sql.DB
}

func NewMysql() *MysqlManager {
	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(config.Conf.Database.SleepTime)*time.Second)
	defer cancel()
	var dsn = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		config.Conf.Database.MysqlConf.Username,
		config.Conf.Database.MysqlConf.Password,
		config.Conf.Database.MysqlConf.Host,
		config.Conf.Database.MysqlConf.Port,
		config.Conf.Database.MysqlConf.Database,
	)
	client, err := gorm.Open(mysql.New(mysql.Config{
		DSN: dsn,
	}), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			TablePrefix:   config.Conf.Database.MysqlConf.Prefix, //表名前缀，都加上f_
			SingularTable: true,                                  //单数表名
			NoLowerCase:   false,                                 //不要小写转换
			//NameReplacer:  strings.NewReplacer("CID", "Cid"), // use name replacer to change struct/field name before convert it to db name
		},
		Logger: logger.New(
			log.New(logs.LogFile(config.Conf.Log.SqlFile), "["+config.Conf.AppName+"]", log.LstdFlags), // io writer
			logger.Config{
				SlowThreshold:             time.Second, // 慢查询的阈值
				LogLevel:                  logger.Info, // 日志级别
				IgnoreRecordNotFoundError: false,       // 是否忽略 record not found 错误，默认为 false，如果设置为 true，则在查询结果为空时不会打印
				ParameterizedQueries:      true,        // Don't include params in the SQL logs
				Colorful:                  false,       // Disable color
			},
		),
		DryRun:      false, // 生成 SQL 但不执行，可以用于准备或测试生成的 SQL
		PrepareStmt: false, //  在执行任何 SQL 时都会创建一个 prepared statement 并将其缓存，以提高后续的效率

	})
	if err != nil {
		logs.Fatal("mysql connect err:%v", err)
		return nil
	}
	db, _ := client.DB()
	m := &MysqlManager{
		Client: client,
		DB:     db,
	}
	m.Client.WithContext(ctx)
	return m
}

func (m *MysqlManager) Close() {
	err := m.DB.Close()
	if err != nil {
		logs.Fatal("mongo close err:%v", err)
	}
}
